home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / Pascal / Applications / NIH Image 1.55 / Source / File1.p < prev    next >
Encoding:
Text File  |  1994-04-28  |  87.5 KB  |  2,037 lines  |  [TEXT/PJMM]

  1. ImportFile (FileName: str255; RefNum: integer): boolean;
  2.     procedure RevertToSaved;
  3.     procedure SaveAs (name: str255; RefNum: integer);
  4.     procedure Export (name: str255; RefNum: integer);
  5.     procedure FindWhatToPrint;
  6.     procedure UpdateFileMenu;
  7.     procedure SaveAsText (fname: str255; RefNum: integer);
  8.     procedure SaveAll;
  9.     procedure UpdateWindowsMenuItem (PicSize: LongInt; title: str255; PicNum: integer);
  10.     function OpenPICS (name: str255; fRefNum: integer): boolean;
  11.     procedure RescaleToEightBits;
  12.  
  13.  
  14. implementation
  15.  
  16.     var
  17.         OpenAllFiles, UseExistingLUT, PICTReadErr: boolean;
  18.         SaveRefNum: integer;
  19.         TempStackInfo: StackInfoRec;
  20.         PictSrcRect: rect;
  21.  
  22. {$PUSH}
  23. {$D-}
  24.  
  25.     procedure LookForCluts (fname: str255; vnum: integer);
  26.         var
  27.             RefNum: integer;
  28.             err: OSErr;
  29.             ok1, ok2: boolean;
  30.     begin
  31.         if not UseExistingLUT then begin
  32.                 err := SetVol(nil, vnum);
  33.                 refNum := OpenResFile(fname);
  34.                 if RefNum <> -1 then begin
  35.                         ok1 := LoadCLUTResource(KlutzID);
  36.                         if not ok1 then
  37.                             ok2 := LoadCLUTResource(PixelPaintID);
  38.                         CloseResFile(refNum);
  39.                     end;
  40.             end;
  41.     end;
  42.  
  43.  
  44.  
  45.     function OpenImageHeader (f: integer; fname: str255; vnum: integer): boolean;
  46.         var
  47.             ByteCount: LongInt;
  48.             err: OSErr;
  49.             TempHdr: PicHeader;
  50.             i, OldNExtra, p1x, p2x: integer;
  51.             ok: boolean;
  52.             hUnitsKind: UnitsType;
  53.     begin
  54.         ByteCount := HeaderSize;
  55.         err := SetFPos(f, fsFromStart, info^.HeaderOffset);
  56.         err := fsread(f, ByteCount, @TempHdr);
  57.         if CheckIO(err) <> NoErr then begin
  58.                 OpenImageHeader := false;
  59.                 exit(OpenImageHeader);
  60.             end;
  61.         with info^, TempHdr do begin
  62.                 if PictureType <> TiffFile then begin
  63.                         nlines := hnlines;
  64.                         PixelsPerLine := hPixelsPerLine;
  65.                     end;
  66.                 if (hversion > 54) and not UseExistingLUT then begin
  67.                         OldNExtra := nExtraColors;
  68.                         nExtraColors := hnExtraColors;
  69.                         ExtraColors := hExtraColors;
  70.                         if (nExtraColors > 0) or (OldNExtra <> nExtraColors) then
  71.                             RedrawLUTWindow;
  72.                     end;
  73.                 if (hversion >= 42) and not UseExistingLUT then begin
  74.                         if hversion < 142 then begin
  75.                                 LUTMode := hOldLUTMode;
  76.                                 if (LutMode = OldAppleDefault) or (LutMode = OldSpectrum) then
  77.                                     LutMode := ColorLut;
  78.                             end
  79.                         else begin
  80.                                 LUTMode := hLUTMode;
  81.                                 if LutMode = Pseudocolor then begin
  82.                                         if ((hnColors > 32) and (hTable = CustomTable)) or (hTable > spectrum) then
  83.                                             LutMode := ColorLut;
  84.                                     end;
  85.                             end;
  86.                         case LUTMode of
  87.                             PseudoColor: 
  88.                                 if hversion < 142 then begin
  89.                                         nColors := hOldnColors;
  90.                                         for i := 0 to ncolors - 1 do begin
  91.                                                 RedLUT[i] := hr[i];
  92.                                                 GreenLUT[i] := hg[i];
  93.                                                 BlueLUT[i] := hb[i];
  94.                                             end;
  95.                                         ColorEnd := 255 - hOldColorStart;
  96.                                         ColorStart := ColorEnd - nColors * hColorWidth + 1;
  97.                                         if ColorStart < 0 then
  98.                                             ColorStart := 0;
  99.                                         InvertPalette;
  100.                                         FillColor1 := BlackRGB;
  101.                                         FillColor2 := BlackRGB;
  102.                                         ColorTable := CustomTable;
  103.                                         UpdateLUT;
  104.                                     end
  105.                                 else begin {V1.42 or later}
  106.                                         if (hTable <> CustomTable) and (hTable <= spectrum) then begin
  107.                                                 SwitchColorTables(GetColorTableItem(hTable), false);
  108.                                                 if hInvertedTable then
  109.                                                     InvertPalette;
  110.                                             end
  111.                                         else begin
  112.                                                 nColors := hnColors;
  113.                                                 ColorTable := CustomTable;
  114.                                                 if nColors <= 32 then
  115.                                                     for i := 0 to ncolors - 1 do begin
  116.                                                             RedLUT[i] := hr[i];
  117.                                                             GreenLUT[i] := hg[i];
  118.                                                             BlueLUT[i] := hb[i];
  119.                                                         end;
  120.                                             end;
  121.                                         ColorStart := hColorStart;
  122.                                         ColorEnd := hColorEnd;
  123.                                         FillColor1 := hFill1;
  124.                                         FillColor2 := hFill2;
  125.                                         UpdateLUT;
  126.                                         UpdateMap;
  127.                                     end; {v1.42 or later}
  128.                             GrayScale: 
  129.                                 ResetGrayMap;
  130.                             ColorLut, CustomGrayscale: 
  131.                                 if PictureType <> PictFile then begin
  132.                                         if ColorMapOffset > 0 then
  133.                                             GetTiffColorMap(f)
  134.                                         else
  135.                                             LookForCluts(fname, vnum);
  136.                                     end;
  137.                             otherwise
  138.                         end; {case}
  139.                         if hLutMode = CustomGrayscale then
  140.                             LutMode := CustomGrayscale;
  141.                     end;{if}
  142.                 if (hversion >= 65) and ((ForegroundIndex <> hForegroundIndex) or (BackgroundIndex <> hBackgroundIndex)) then begin
  143.                         SetForegroundColor(hForegroundIndex);
  144.                         SetBackgroundColor(hBackgroundIndex);
  145.                     end;
  146.                 if (hversion > 88) and (LUTMode = GrayScale) and not UseExistingLUT then begin
  147.                         if hversion < 138 then begin
  148.                                 p1x := 255 - hp2x;
  149.                                 p2x := 255 - hp1x;
  150.                             end
  151.                         else begin
  152.                                 p1x := hp1x;
  153.                                 p2x := hp2x
  154.                             end;
  155.                         nColors := 256;
  156.                         ColorStart := p1x;
  157.                         ColorEnd := p2x;
  158.                         UpdateLUT;
  159.                     end;
  160.                 if hversion > 106 then begin
  161.                         xSpatialScale := hXSpatialScale;
  162.                         ySpatialScale := xSpatialScale;
  163.                         PixelAspectRatio := 1.0;
  164.                         SpatiallyCalibrated := xSpatialScale <> 0.0;
  165.                     end;
  166.                 if hversion > 140 then begin
  167.                         PixelAspectRatio := hPixelAspectRatio;
  168.                         ySpatialScale := xSpatialScale / PixelAspectRatio;
  169.                     end;
  170.                 if hversion > 153 then
  171.                     xUnit := hXUnit
  172.                 else begin
  173.                         hUnitsKind := UnitsType(hUnitsID - 5);
  174.                         GetXUnits(hUnitsKind);
  175.                     end;
  176.                 if xUnit = 'pixel' then
  177.                     SpatiallyCalibrated := false;
  178.                 if ((hnCoefficients > 0) and (hfit < UncalibratedOD)) or (hfit = UncalibratedOD) then begin
  179.                         if (hfit = SpareFit1) or (hfit = SpareFit2) then begin
  180.                                 DensityCalibrated := false;
  181.                                 DrawLabels('', '', '');
  182.                             end
  183.                         else begin
  184.                                 fit := hfit;
  185.                                 if hfit <> UncalibratedOD then begin
  186.                                         nCoefficients := hnCoefficients;
  187.                                         Coefficient := hCoeff;
  188.                                     end;
  189.                                 UnitOfMeasure := hUM;
  190.                                 DensityCalibrated := true;
  191.                                 if hversion >= 144 then
  192.                                     ZeroClip := hZeroClip
  193.                                 else
  194.                                     ZeroClip := false;
  195.                             end;
  196.                     end
  197.                 else begin
  198.                         DensityCalibrated := false;
  199.                         DrawLabels('', '', '');
  200.                     end;
  201.                 BinaryPic := hBinaryPic;
  202.                 if hSliceEnd > 1 then begin
  203.                         SliceStart := hSliceStart;
  204.                         SliceEnd := hSliceEnd;
  205.                         if SliceEnd > 254 then
  206.                             SliceEnd := 254;
  207.                     end;
  208.                 if hNSlices > 1 then begin
  209.                         with TempStackInfo do begin
  210.                                 nSlices := hNSlices;
  211.                                 if nSlices > MaxSlices then
  212.                                     nSlices := MaxSlices;
  213.                                 CurrentSlice := hCurrentSlice;
  214.                                 if (hCurrentSlice < 1) or (hCurrentSlice > nSlices) then
  215.                                     CurrentSlice := 1;
  216.                                 SliceSpacing := hSliceSpacing;
  217.                                 LoopTime := hLoopTime;
  218.                             end;
  219.                     end;
  220.                 iVersion := hVersion;
  221.                 OpenImageHeader := true
  222.             end;
  223.     end;
  224.  
  225.  
  226.     function OpenHeader (f: integer; fname: str255; vnum: integer; var NextTiffIFD: LongInt): boolean;
  227.         var
  228.             ByteCount, FileSize, DirOffset, MaxImages: LongInt;
  229.             hdr: packed array[1..512] of byte;
  230.             err: OSErr;
  231.             TempHdr: PicHeader;
  232.             TiffInfo: TiffInfoRec;
  233.     begin
  234.         with info^ do begin
  235.                 if (WhatToOpen = OpenUnknown) or (WhatToOpen = OpenImported) then begin
  236.                         err := SetFPos(f, fsFromStart, 0);
  237.                         ByteCount := 8;
  238.                         err := fsread(f, ByteCount, @hdr);
  239.                         if ((hdr[1] = 73) and (hdr[2] = 73)) or ((hdr[1] = 77) and (hdr[2] = 77)) then
  240.                             WhatToOpen := OpenTIFF
  241.                         else if WhatToOpen = OpenUnknown then
  242.                             WhatToOpen := OpenImage
  243.                         else
  244.                             WhatToOpen := OpenMCID;
  245.                     end;
  246.                 StackInfo := nil;
  247.                 with TempStackInfo do begin
  248.                         nSlices := 0;
  249.                         CurrentSlice := 1;
  250.                         SliceSpacing := 0.0;
  251.                         LoopTime := 0.0;
  252.                     end;
  253.                 NextTiffIFD := 0;
  254.                 iVersion := 0;
  255.                 case WhatToOpen of
  256.                     OpenImage:  begin
  257.                             err := SetFPos(f, fsFromStart, 0);
  258.                             ByteCount := 8;
  259.                             err := fsread(f, ByteCount, @TempHdr);
  260.                             if TempHdr.FileID = FileID8 then begin
  261.                                     HeaderOffset := 0;
  262.                                     PictureType := normal
  263.                                 end
  264.                             else begin
  265.                                     HeaderOffset := -1;
  266.                                     BlockMove(@TempHdr, @hdr, 8);
  267.                                     nlines := hdr[1] + hdr[2] * 256;
  268.                                     PixelsPerLine := hdr[3] + hdr[4] * 256;
  269.                                     PictureType := PDP11;
  270.                                 end;
  271.                             ImageDataOffset := 512;
  272.                         end;
  273.                     OpenMCID:  begin
  274.                             err := SetFPos(f, fsFromStart, 0);
  275.                             ByteCount := 4;
  276.                             err := fsread(f GreenLUT[i];
  277.                                     hb[i] := BlueLUT[i];
  278.                                 end;
  279.                     end;
  280.                 hColorStart := ColorStart;
  281.                 hColorEnd := ColorEnd;
  282.                 hFill1 := FillColor1;
  283.                 hFill2 := FillColor2;
  284.                 hTable := ColorTable;
  285.                 hInvertedTable := InvertedColorTable;
  286.                 hOldColorStart := 255 - ColorEnd;
  287.                 if nColors > 0 then
  288.                     hColorWidth := (ColorEnd - ColorStart) div nColors
  289.                 else
  290.                     hColorWidth := 1;
  291.                 hnExtraColors := nExtraColors;
  292.                 hExtraColors := ExtraColors;
  293.                 hForegroundIndex := ForegroundIndex;
  294.                 hBackgroundIndex := BackgroundIndex;
  295.                 hXSpatialScale := xSpatialScale;
  296.                 hScaleMagnification := 1.0;
  297.                 hPixelAspectRatio := PixelAspectRatio;
  298.                 hUnitsID := 14; {Pixels. For backward compatibility only since hUnits no longer used.}
  299.                 if SpatiallyCalibrated then begin
  300.                         GetUnitsKind(UnitsKind, UnitsPerCM);
  301.                         hUnitsID := ord(UnitsKind) + 5;
  302.                         if hUnitsID > 14 then
  303.                             hUnitsID := 14;
  304.                     end;
  305.                 FindPoints(hp1x, hp1y, hp2x, hp2y);
  306.                 if not DensityCalibrated then
  307.                     hnCoefficients := 0
  308.                 else
  309.                     hnCoefficients := nCoefficients;
  310.                 hfit := fit;
  311.                 hCoeff := Coefficient;
  312.                 hZeroClip := ZeroClip;
  313.                 hUM := UnitOfMeasure;
  314.                 hBinaryPic := BinaryPic;
  315.                 hSliceStart := SliceStart;
  316.                 hSliceEnd := SliceEnd;
  317.                 if StackInfo <> nil then
  318.                     with StackInfo^ do begin
  319.                             hNSlices := nSlices;
  320.                             hSliceSpacing := SliceSpacing;
  321.                             hCurrentSlice := CurrentSlice;
  322.                             hLoopTime := LoopTime;
  323.                         end
  324.                 else begin
  325.                         hNSlices := 0;
  326.                         hSliceSpacing := 0.0;
  327.                         hCurrentSlice := 0;
  328.                         hLoopTime := 0.0;
  329.                     end;
  330.                 hXUnit := xUnit;
  331.                 ByteCount := SizeOf(TempHdr);
  332.                 if ByteCount <> HeaderSize then begin
  333.                         NumToString(ByteCount, str);
  334.                         PutMessage('Internal error check: header size is incorrect.');
  335.                         ExitToShell;
  336.                     end;
  337.                 if SavingSelection then begin
  338.                         hnlines := slines;
  339.                         hPixelsPerLine := sPixelsPerLine;
  340.                     end;
  341.                 err := fswrite(f, ByteCount, @TempHdr);
  342.                 SaveHeader := CheckIO(err);
  343.             end; {with}
  344.     end;
  345.  
  346.  
  347.     procedure PackLines;
  348.   {For odd width images, removes the extra bytes at the end of each line required to make RowBytes even.}
  349.         var
  350.             i: integer;
  351.             SrcPtr, DstPtr: ptr;
  352.     begin
  353.         with info^ do begin
  354.                 SrcPtr := ptr(ord4(PicBaseAddr) + BytesPerRow);
  355.                 DstPtr := ptr(ord4(PicBaseAddr) + PixelsPerLine);
  356.                 for i := 1 to nlines - 1 do begin
  357.                         BlockMove(SrcPtr, DstPtr, PixelsPerLine);
  358.                         SrcPtr := ptr(ord4(SrcPtr) + BytesPerRow);
  359.                         DstPtr := ptr(ord4(DstPtr) + PixelsPerLine);
  360.                     end;
  361.             end;
  362.     end;
  363.  
  364.  
  365.     procedure UnpackLines;
  366.   {For odd width images, adds an extra byte to each line so RowBytes is even.}
  367.         var
  368.             i: integer;
  369.             SrcPtr, DstPtr: ptr;
  370.     begin
  371.         with info^ do begin
  372.                 SrcPtr := ptr(ord4(PicBaseAddr) + LongInt(nlines - 1) * PixelsPerLine);
  373.                 DstPtr := ptr(ord4(PicBaseAddr) + LongInt(nlines - 1) * BytesPerRow);
  374.                 for i := 1 to nlines - 1 do begin
  375.                         BlockMove(SrcPtr, DstPtr, PixelsPerLine);
  376.                         SrcPtr := ptr(ord4(SrcPtr) - PixelsPerLine);
  377.                         DstPtr := ptr(ord4(DstPtr) - BytesPerRow);
  378.                     end;
  379.             end;
  380.     end;
  381.  
  382.  
  383.     function WriteSlices (f: integer): integer;
  384.         var
  385.             ByteCount, SelectionSize: LongInt;
  386.             i, err, SaveCS: integer;
  387.     begin
  388.         with info^, Info^.StackInfo^ do begin
  389.                 SaveCS := CurrentSlice;
  390.                 for i := 1 to nSlices do begin
  391.                         CurrentSlice := i;
  392.                         SelectSlice(CurrentSlice);
  393.                         UpdateTitleBar;
  394.                         ByteCount := ImageSize;
  395.                         if odd(PixelsPerLine) then
  396.                             PackLines;
  397.                         err := fswrite(f, ByteCount, PicBaseAddr);
  398.                         if odd(PixelsPerLine) then
  399.                             UnpackLines;
  400.                         if err <> 0 then
  401.                             leave;
  402.                     end;
  403.                 CurrentSlice := SaveCS;
  404.                 SelectSlice(CurrentSlice);
  405.                 UpdateTitleBar;
  406.                 WriteSlices := err;
  407.             end;
  408.     end;
  409.  
  410.  
  411.     procedure WriteSelection (f: integer; sLines, sPixelsPerLine: LongInt);
  412.   {Contributed by Edward J. Huff(huff@mcclb0.med.nyu.edu).}
  413.         var
  414.             size, offset, ByteCount, BytesDone: LongInt;
  415.             src, dst: ptr;
  416.             err: OSErr;
  417.     begin
  418.         if sPixelsPerLine > UndoBufSize then
  419.             exit(WriteSelection);
  420.         size := sLines * sPixelsPerLine;
  421.         with info^, info^.RoiRect do begin
  422.                 offset := LongInt(top) * BytesPerRow + left;
  423.                 src := ptr(ord4(PicBaseAddr) + offset);
  424.                 BytesDone := 0;
  425.                 while BytesDone < size do begin
  426.                         ByteCount := 0;
  427.                         dst := UndoBuf;
  428.                         while ((ByteCount + sPixelsPerLine) < UndoBufSize) and (BytesDone < size) do begin
  429.                                 BlockMove(src, dst, sPixelsPerLine);
  430.                                 src := ptr(ord4(src) + BytesPerRow);
  431.                                 dst := ptr(ord4(dst) + sPixelsPerLine);
  432.                                 ByteCount := ByteCount + sPixelsPerLine;
  433.                                 BytesDone := BytesDone + sPixelsPerLine;
  434.                             end;
  435.                         err := fswrite(f, ByteCount, UndoBuf);
  436.                     end;
  437.                 SetupUndo; {Needed for drawing roi outline}
  438.             end
  439.     end;
  440.  
  441.  
  442.     function SaveTiffFile (fname: str255; vnum: integer; slines, sPixelsPerLine: integer; SavingSelection: boolean): boolean;
  443.         var
  444.             f, err, i, width, height: integer;
  445.             HdrSize, ByteCount, ctabSize, StackTiffDirSize, ImageDataSize: LongInt;
  446.             TheInfo: FInfo;
  447.             MCIDHeader: packed array[1..4] of byte;
  448.             SaveColorMap: boolean;
  449.     begin
  450.         SaveTiffFile := false;
  451.         ShowWatch;
  452.         err := fsopen(fname, vNum, f);
  453.         if CheckIO(err) <> 0 then
  454.             exit(SaveTiffFile);
  455.         with Info^ do begin
  456.                 SaveColorMap := (LutMode <> Grayscale) and (SaveAsWhat <> asRawData);
  457.                 if SaveAsWhat = SaveAsMCID then begin
  458.                         if SavingSelection then begin
  459.                                 width := sPixelsPerLine;
  460.                                 height := slines;
  461.                             end
  462.                         else begin
  463.                                 width := PixelsPerLine;
  464.                                 height := nLines;
  465.                             end;
  466.                         MCIDHeader[1] := (width - 1) mod 256;
  467.                         MCIDHeader[2] := (width - 1) div 256;
  468.                         MCIDHeader[3] := (height - 1) mod 256;
  469.                         MCIDHeader[4] := (height - 1) div 256;
  470.                         ByteCount := 4;
  471.                         err := fswrite(f, ByteCount, @MCIDHeader);
  472.                     end;
  473.                 HeaderOffset := TiffDirSize;
  474.                 ImageDataOffset := TiffDirSize + HeaderSize;
  475.                 if SaveColorMap then
  476.                     ctabSize := SizeOf(TiffColorMapType)
  477.                 else
  478.                     ctabSize := 0;
  479.                 StackTiffDirSize := 0;
  480.                 if SavingSelection then
  481.                     ImageDataSize := LongInt(slines) * sPixelsPerLine
  482.                 else if StackInfo <> nil then begin
  483.                         ImageDataSize := ImageSize * StackInfo^.nSlices;
  484.                         StackTiffDirSize := SizeOf(StackIFDType) * (StackInfo^.nSlices - 1)
  485.                     end
  486.                 else
  487.                     ImageDataSize := ImageSize;
  488.                 if (SaveAsWhat <> asRawData) and (SaveAsWhat <> SaveAsMCID) then begin
  489.                         if SaveTiffDir(f, slines, sPixelsPerLine, SavingSelection, ctabSize, ImageDataSize) <> NoErr then begin
  490.                                 err := fsclose(f);
  491.                                 err := FSDelete(fname, vnum);
  492.                                 exit(SaveTiffFile)
  493.                             end;
  494.                         err := SetFPos(f, FSFromStart, TiffDirSize);
  495.                         if SaveHeader(f, slines, sPixelsPerLine, vnum, fname, SavingSelection, true) <> NoErr then begin
  496.                                 err := fsclose(f);
  497.                                 err := FSDelete(fname, vnum);
  498.                                 exit(SaveTiffFile)
  499.                             end;
  500.                     end;
  501.                 if SaveAsWhat = SaveAsMCID then
  502.                     KillRoi;
  503.                 if SavingSelection then
  504.                     WriteSelection(f, sLines, sPixelsPerLine)
  505.                 else if StackInfo <> nil then
  506.                     err := WriteSlices(f)
  507.                 else begin
  508.                         ByteCount := ImageDataSize;
  509.                         if odd(PixelsPerLine) then
  510.                             PackLines;
  511.                         err := fswrite(f, ByteCount, PicBaseAddr);
  512.                         if odd(PixelsPerLine) then
  513.                             UnpackLines;
  514.                     end;
  515.                 if SaveAsWhat = SaveAsMCID then
  516.                     InvertPic;
  517.                 if CheckIO(err) <> 0 then begin
  518.                         err := fsclose(f);
  519.                         err := FSDelete(fname, vnum);
  520.                         exit(SaveTiffFile)
  521.                     end;
  522.                 if SaveAsWhat = asRawData then
  523.                     HdrSize := 0
  524.                 else if SaveAsWhat = SaveAsMCID then begin
  525.                         HdrSize := 4;
  526.                         SaveAsWhat := asRawData;
  527.                     end
  528.                 else
  529.                     HdrSize := HeaderSize + TiffDirSize;
  530.                 if SaveColorMap then
  531.                     SaveTiffColorMap(f, ImageDataSize);
  532.                 if StackTiffDirSize > 0 then
  533.                     err := WriteExtraTiffIFDs(f, ImageDataSize, cTabSize);
  534.                 err := SetEOF(f, HdrSize + ImageDataSize + ctabSize + StackTiffDirSize);
  535.                 err := fsclose(f);
  536.                 err := GetFInfo(fname, vnum, TheInfo);
  537.                 if TheInfo.fdCreator <> 'Imag' then begin
  538.                         TheInfo.fdCreator := 'Imag';
  539.                         err := SetFInfo(fname, vnum, TheInfo);
  540.                     end;
  541.                 if SaveAsWhat = asRawData then begin
  542.                         TheInfo.fdType := 'RawD';
  543.                         err := SetFInfo(fnae;
  544.         if (item >= TiffID) and (item <= OutlineID) then begin
  545.                 SaveAsWhat := SaveAsWhatType(item - TiffID);
  546.                 if not NameEdited then begin
  547.                         SetDString(theDialog, EditTextID, SuggestedName);
  548.                         SelIText(theDialog, EditTextID, 0, 32767);
  549.                     end;
  550.                 for i := TiffID to OutlineID do
  551.                     SetDialogItem(theDialog, i, 0);
  552.                 SetDialogItem(theDialog, item, 1);
  553.             end;
  554.         SaveAsHook := item;
  555.     end;
  556.  
  557.  
  558.     procedure SaveAs (name: str255; RefNum: integer);
  559.         const
  560.             CustomDialogID = 60;
  561.         var
  562.             where: Point;
  563.             reply: SFReply;
  564.             isSelection: boolean;
  565.             kind: integer;
  566.     begin
  567.         with info^ do begin
  568.                 if SaveAllState = SaveAllStage2 then begin
  569.                         name := title;
  570.                         RefNum := SaveRefNum;
  571.                         if SaveAsWhat = AsPalette then
  572.                             SaveAsWhat := AsTiff;
  573.                     end
  574.                 else if (name = '') or ((RefNum = 0) and (pos(':', name) = 0)) then begin
  575.                         where.v := 50;
  576.                         where.h := 50;
  577.                         if (StackInfo = nil) and (SaveAsWhat = asPICS) then
  578.                             SaveAsWhat := asTIFF;
  579.                         if (StackInfo <> nil) and ((SaveAsWhat = asPICT) or (SaveAsWhat = asMacPaint)) then
  580.                             SaveAsWhat := asTIFF;
  581.                         if name = '' then
  582.                             name := SuggestedName;
  583.                         SFPPutFile(Where, 'Save as?', name, @SaveAsHook, reply, CustomDialogID, nil);
  584.                         if not reply.good then begin
  585.                                 SaveAllState := NoSaveAll;
  586.                                 macro := false;
  587.                                 exit(SaveAs);
  588.                             end;
  589.                         with reply do begin
  590.                                 name := fname;
  591.                                 RefNum := vRefNum;
  592.                                 DefaultRefNum := RefNum;
  593.                             end;
  594.                     end;
  595.                 if StackInfo <> nil then begin
  596.                         if SaveAsWhat <> asOutline then
  597.                             KillRoi;
  598.                         SaveAllState := NoSaveAll;
  599.                         if not ((SaveAsWhat = asTIFF) or (SaveAsWhat = asPICS) or (SaveAsWhat = asPalette) or (SaveAsWhat = asOutline)) then begin
  600.                                 PutMessage('Stacks can only be saved in TIFF or PICS format.');
  601.                                 SaveAsWhat := asTIFF;
  602.                                 exit(SaveAs);
  603.                             end;
  604.                     end;
  605.                 isSelection := RoiShowing and (RoiType = RectRoi);
  606.                 if SaveAllState = SaveAllStage1 then begin
  607.                         SaveRefNum := RefNum;
  608.                         SaveAllState := SaveAllStage2;
  609.                     end;
  610.                 case SaveAsWhat of
  611.                     asTiff, asRawData: 
  612.                         if isSelection then
  613.                             SaveSelection(name, RefNum, false)
  614.                         else
  615.                             SaveAsTIFF(name, RefNum, 0, 0, false);
  616.                     asPict: 
  617.                         if isSelection then
  618.                             SaveAsPICT(name, RefNum, true)
  619.                         else
  620.                             SaveAsPICT(name, RefNum, false);
  621.                     asMacPaint: 
  622.                         SaveAsMacPaint(name, RefNum);
  623.                     asPICS: 
  624.                         SaveAsPICS(name, RefNum);
  625.                     AsPalette: 
  626.                         SaveColorTable(name, RefNum);
  627.                     AsOutline: 
  628.                         SaveOutline(name, RefNum);
  629.                 end; {case}
  630.                 if (SaveAsWhat = asRawData) and (SaveAllState <> SaveAllStage2) then
  631.                     SaveAsWhat := asTIFF;
  632.             end; {with}
  633.     end;
  634.  
  635.  
  636.     procedure SaveFile;
  637.         var
  638.             fname: str255;
  639.             size: LongInt;
  640.             ok: boolean;
  641.     begin
  642.         if CurrentWindow = ResultsKind then begin
  643.                 Export('', 0);
  644.                 exit(SaveFile);
  645.             end;
  646.         if CurrentWindow = TextKind then begin
  647.                 SaveText;
  648.                 exit(SaveFile);
  649.             end;
  650.         if OpPending then
  651.             KillRoi;
  652.         with Info^ do begin
  653.                 fname := title;
  654.                 size := 0;
  655.                 if PictureType = TiffFile then
  656.                     ok := SaveTiffFile(fname, vref, 0, 0, false)
  657.                 else if PictureType = PictFile then
  658.                     ok := SavePICTFile(fname, vref, false, false)
  659.                 else
  660.                     SaveAs('', 0);
  661.             end;
  662.     end;
  663.  
  664.  
  665.     function SaveChanges: integer;
  666.         const
  667.             yesID = 1;
  668.             noID = 2;
  669.             cancelID = 3;
  670.         var
  671.             id: integer;
  672.             reply: SFReply;
  673.     begin
  674.         id := 0;
  675.         if info^.changes then
  676.             with info^ do begin
  677.                     if CommandPeriod or MakingStack or (macro and ((MacroCommand = DisposeC) or (MacroCommand = DisposeAllC))) then begin
  678.                             SaveChanges := ok;
  679.                             exit(SaveChanges);
  680.                         end;
  681.                     ParamText(title, '', '', '');
  682.                     InitCursor;
  683.                     id := alert(600, nil);
  684.                     if id = yesID then begin
  685.                             SaveFile;
  686.                             InitCursor;
  687.                         end; {if yes}
  688.                 end; {if changes}
  689.         if (id = cancelID) or ((id = yesID) and (info^.changes)) then
  690.             SaveChanges := cancel
  691.         else
  692.             SaveChanges := ok;
  693.     end;
  694.  
  695.  
  696.     function CloseAWindow (WhichWindow: WindowPtr): integer;
  697.         var
  698.             i, kind, n: integer;
  699.             TempInfo: InfoPtr;
  700.             TempTexlsPerLine > MaxLine then
  701.                     exit(Read4BitTIFF);
  702.                 ByteCount := (PixelsPerLine + 1) div 2;
  703.                 for vloc := 0 to nLines - 1 do begin
  704.                         err := FSRead(f, ByteCount, @PackedLine);
  705.                         i := 0;
  706.                         for hloc := 0 to PixelsPerLine - 1 do
  707.                             if odd(hloc) then begin
  708.                                     UnpackedLine[hloc] := bsl(band(PackedLine[i], $F), 4);
  709.                                     i := i + 1;
  710.                                 end
  711.                             else
  712.                                 UnpackedLine[hloc] := band(PackedLine[i], $F0);
  713.                         PutLine(0, vloc, PixelsPerLine, UnpackedLine);
  714.                     end;
  715.             end; {with}
  716.     end;
  717.  
  718.  
  719. {$POP}
  720.  
  721.  
  722.     procedure ReadStackSlices (f, nExtraImages: integer; var table: TiffIFDTable);
  723.         var
  724.             i, err, SaveCS: integer;
  725.             h: handle;
  726.             DataSize: LongInt;
  727.             PartialStack: boolean;
  728.     begin
  729.         ShowMessage(CmdPeriodToStop);
  730.         PartialStack := false;
  731.         with info^ do begin
  732.                 StackInfo := StackInfoPtr(NewPtr(SizeOf(StackInfoRec)));
  733.                 if StackInfo = nil then
  734.                     exit(ReadStackSlices);
  735.             end;
  736.         with info^, info^.StackInfo^ do begin
  737.                 nSlices := nExtraImages + 1;
  738.                 CurrentSlice := TempStackInfo.CurrentSlice;
  739.                 if (CurrentSlice < 1) or (CurrentSlice > nSlices) then
  740.                     CurrentSlice := 1;
  741.                 SliceSpacing := TempStackInfo.SliceSpacing;
  742.                 LoopTime := TempStackInfo.LoopTime;
  743.                 SaveCS := CurrentSlice;
  744.                 PicBaseH[1] := PicBaseHandle;
  745.                 revertable := false;
  746.                 for i := 2 to nSlices do begin
  747.                         h := GetBigHandle(PixMapSize);
  748.                         if h = nil then begin
  749.                                 nSlices := i - 1;
  750.                                 PutMessage(concat('Not enough memory to open all ', long2str(nExtraImages + 1), ' slices in the stack.'));
  751.                                 PartialStack := true;
  752.                                 leave;
  753.                             end;
  754.                         PicBaseH[i] := h;
  755.                         CurrentSlice := i;
  756.                         SelectSlice(i);
  757.                         UpdateTitleBar;
  758.                         DataSize := ImageSize;
  759.                         err := SetFPos(f, fsFromStart, table[i - 1].offset);
  760.                         err := fsread(f, DataSize, h^);
  761.                         if odd(PixelsPerLine) then
  762.                             UnpackLines;
  763.                         if (PictureType = InvertedTIFF) or ((PictureType = Imported) and ImportInvert) then
  764.                             InvertPic;
  765.                         UpdatePicWindow;
  766.                         if CommandPeriod then begin
  767.                                 beep;
  768.                                 if i < nSlices then
  769.                                     PartialStack := true;
  770.                                 nSlices := i;
  771.                                 wait(60);
  772.                                 leave;
  773.                             end;
  774.                     end; {for}
  775.                 CurrentSlice := SaveCS;
  776.                 if CurrentSlice > nSlices then
  777.                     CurrentSlice := 1;
  778.                 SelectSlice(CurrentSlice);
  779.                 if PartialStack then begin
  780.                         vref := 0;
  781.                         PictureType := NewPicture;
  782.                         title := concat(title, '@');
  783.                     end;
  784.                 UpdateTitleBar;
  785.                 UpdateWindowsMenuItem(PixMapSize * nSlices, title, PicNum);
  786.             end;
  787.     end;
  788.  
  789.  
  790.     procedure OpenStack (f: integer);
  791.         var
  792.             table: TiffIFDTable;
  793.             i, nExtraImages: integer;
  794.             where: LongInt;
  795.     begin
  796.         nExtraImages := TempStackInfo.nSlices - 1;
  797.         with info^ do begin
  798.                 where := ImageDataOffset;
  799.                 for i := 1 to nExtraImages do
  800.                     with table[i] do begin
  801.                             iWidth := PixelsPerLine;
  802.                             iHeight := nLines;
  803.                             where := where + ImageSize;
  804.                             Offset := where;
  805.                             invert := false;
  806.                         end;
  807.                 ReadStackSlices(f, nExtraImages, table);
  808.             end;
  809.     end;
  810.  
  811.  
  812.     procedure OpenExtraTiffImages (f: integer; NextTiffIFD: LongInt);
  813.         var
  814.             table: TiffIFDTable;
  815.             TiffInfo: TiffInfoRec;
  816.             i, nExtraImages: integer;
  817.             AllSameSize: boolean;
  818.     begin
  819.         nExtraImages := 0;
  820.         repeat
  821.             if not OpenTiffDirectory(f, NextTiffIFD, TiffInfo, false) then
  822.                 exit(OpenExtraTiffImages);
  823.             nExtraImages := nExtraImages + 1;
  824.             with TiffInfo, table[nExtraImages] do begin
  825.                     iWidth := width;
  826.                     iHeight := height;
  827.                     Offset := OffsetToData;
  828.                     invert := ZeroIsBlack;
  829.                     NextTiffIFD := NextIFD;
  830.                 end;
  831.         until (NextTiffIFD = 0) or (nExtraImages = MaxSlices);
  832.         AllSameSize := true;
  833.         with info^ do begin
  834.                 for i := 1 to nExtraImages do
  835.                     AllSameSize := AllSameSize and (PixelsPerLine = table[i].iWidth) and (nLines = table[i].iHeight);
  836.                 if AllSameSize and not odd(PixelsPerLine) then
  837.                     ReadStackSlices(f, nExtraImages, table);
  838.             end;
  839.     end;
  840.  
  841.  
  842.     function OpenFile (fname: str255; vnum: integer): boolean;
  843.         var
  844.             ticks, ByteCount, i, DataSize, NextTiffIFD: LongInt;
  845.             err: OSErr;
  846.             f: integer;
  847.             line, pixel: integer;
  848.             iptr, p: ptr;
  849.             SaveInfo: InfoPtr;
  850.     begin
  851.         OpenFile := false;
  852.         ShowWatch;
  853.         err := fsopen(fname, vNum, f);
  854.         SaveInfo := Info;
  855.         iptr := NewPtr(SizeOf(PicInfo));
  856.         if iptr = nil then begin
  857.                 PutMemoryAlert;
  858.                 err := fsclose(f);
  859.                 exit(OpenFile)
  860.             end;
  861.         Info := pointer(iptr);
  862.         CloneInfo(SaveInfo^, Info^);
  863.         with Info^ do begin
  864.                 ColorMapOffset := 0;
  865.                 if not OpenHeader(f, fname, vnum, NextTiffIFD) then begin
  866.                         DisposPtr(iptr);
  867.                         err := fsclose(f);
  868.                         Info := SaveInfo;
  869.                         exit(OpenFile)
  870.                     end;
  871.                 p := GetImageMemory(SaveInfo);
  872.                 if p = nil then begin
  873.                         err := fsclose(f);
  874.                         exit(OpenFile)
  875.                     end;
  876.                 PicBaseAddr := p;
  877.                 MakeNewWindow(fname);
  878.                 err := SetFPos(f, fsFromStart, ImageDataOffset);
  879.                 if PictureType = FourBitTIFF then
  880.                     Read4BitTIFF(f)
  881.                 else begin
  882.                         DataSize := LongInt(nlines) * PixelsPerLine;
  883.                         err := fsread(f, DataSize, PicBaseAddr);
  884.                         if CheckIO(err) <> NoErr then begin
  885.                                 err := fsclose(f);
  886.                                 exit(OpenFile)
  887.                             end;
  888.                     end;
  889.                 if odd(PixelsPerLine) and (PictureType <> FourBitTiff) then
  890.                     UnpackLines;
  891.                 if (PictureType = pdp11) or (PictureType = InvertedTIFF) or ((PictureType = Imported) and (ImportInvert or (WhatToImport = ImportMCID))) then
  892.                     InvertPic;
  893.                 if PictureType = FourBitTIFF then
  894.                     PictureType := imported;
  895.                 if (ColorMapOffset > 0) and (iVersion = 0) then begin
  896.                         FixColors; {Fix colors, if necessary, of imported color TIFF files.}
  897.                         WhatToUndo := NothingToUndo;
  898.                     end;
  899.                 vref := vnum;
  900.                 if PixMapSize > UndoBufSize then
  901.                     PutWarning;
  902.                 revertable := true;
  903.             end; {with}
  904.         if TempStackInfo.nSlices > 0 then
  905.             OpenStack(f)
  906.         else if NextTiffIFD > 0 then
  907.             OpenExtraTiffImages(f, NextTiffIFD);
  908.         err := fsclose(f);
  909.         OpenFile := true;
  910.     end;
  911.  
  912.  
  913. {$PUSH}
  914. {$D-}
  915.  
  916.  
  917.     procedure ScaleToEightBits (f: integer);
  918.         type
  919.             PixelLUTType = packed array[0..65535] of Unsignedbyte;
  920.             PixelLUTPtr = ^PixelLUTType;
  921.             IntLineType = array[0..MaxLine] of integer;
  922.         var
  923.             line: LineType;
  924.             i, j, value, LineSize, offset: LongInt;
  925.             ScaleFactor: extended;
  926.             hloc, vloc, wwidth, wheight, IntValue, SaveBytesPerRow: integer;
  927.             PixelLUT: PixelLUTPtr;
  928.             str1, str2: str255;
  929.             err: integer;
  930.             aLine: IntLineType;
  931.             LinesPerUpdate: integer;
  932.  
  933.         procedure reset;
  934.             var
  935.                 DataSize, SliceOffset: LongInt;
  936.                 p: ptr;
  937.         begin
  938.             with info^ do begin
  939.                     if StackInfo <> nil then
  940.                         SliceOffset := ImageSize * 2 * (StackInfo^.CurrentSlice - 1)
  941.                     else
  942.                         SliceOffset := 0;
  943.                     err := SetFPos(f, fsFromStart, ImageDataOffset + SliceOffset);
  944.                     if DataH <> nil then begin
  945.                             if offset = -1 then begin
  946.                                     hlock(DataH);
  947.                                     DataSize := ImageSize * 2;
  948.                                     err := fsread(f, DataSize, DataH^);
  949.                                 end;
  950.                             offset := 0
  951.                         end;
  952.                 end;
  953.         end;
  954.  
  955.  
  956.         procedure GetIntLine (var line: IntLineType);
  957.             type
  958.                 atype = packed array[1..2] of char;
  959.             var
  960.                 p: ptr;
  961.                 a: atype;
  962.                 c: char;
  963.                 i: integer;
  964.         begin
  965.             with info^ do begin
  966.                     if DataH <> nil then begin
  967.                             p := ptr(ord4(DataH^) + offset);
  968.                             BlockMove(p, @line, LineSize);
  969.                             offset := offset + LineSize;
  970.                         end
  971.                     else
  972.                         err := fsread(f, LineSize, @line);
  973.                     if LittleEndian then
  974.                         for i := 0 to LineSize div 2 - 1 do begin
  975.                                 a := atype(line[i]);
  976.                                 c := a[1];
  977.                                 a[1] := a[2];
  978.                                 a[2] := c;
  979.                                 line[i] := integer(a)
  980.                             end;
  981.                 end;
  982.         end;
  983.  
  984.     begin
  985.         with info^ do begin
  986.                 PixelLUT := PixelLUTPtr(NewPtr(SizeOf(PixelLUTType)));
  987.                 if PixelLUT = nil then begin
  988.                         if DataH <> nil then begin
  989.                                 DisposHandle(DataH);
  990.                                 DataH := nil
  991.                             end;
  992.                         PutMessage('Not enough memory to do 16 to 8-bit scaling.');
  993.                         macro := false;
  994.                         exit(ScaleToEightBits);
  995.                     end;
  996.                 offset := -1;
  997.                 reset;
  998.                 LineSize := PixelsPerLine * 2;
  999.                 LinesPerUpdate := 20000 div PixelsPerLine;
  1000.                 if (AbsoluteMin = 0) and (AbsoluteMax = 0) then begin
  1001.                         AbsoluteMin := 999999;
  1002.                         AbsoluteMax := -999999;
  1003.                         for vloc := 0 to nlines - 1 do begin
  1004.                                 if (vloc mod LinesPerUpdate) = 0 then
  1005.                                     ShowAnimatedWatch;
  1006.                                 GetIntLine(aLine);
  1007.                                 for hloc := 0 to PixelsPerLine - 1 do begin
  1008.                                         value := aLine[hloc];
  1009.                                         if (DataType = SixteenBitsUnsigned) and (value < 0) then
  1010.                                             value := value + 65536;
  1011.                                         if value > AbsoluteMax then
  1012.                                             AbsoluteMax := value;
  1013.                                         if value < AbsoluteMin then
  1014.                                             AbsoluteMin := value;
  1015.                                     end {for hloc:=}
  1016.                             end;{for vloc := }
  1017.                         if (CurrentMin = 0) and (CurrentMax = 0) then begin
  1018.                                 CurrentMin := AbsoluteMin;
  1019.                                 CurrentMax := AbsoluteMax;
  1020.                             end;
  1021.                         reset;
  1022.                     end;
  1023.                 str1 := concat('min=', long2str(CurrentMin), ' (', long2str(AbsoluteMin), ')', cr, 'max=', long2str(CurrentMax), ' (', long2str(AbsoluteMax), ')');
  1024.                 ScaleFactor := 253.0 / (CurrentMax - CurrentMin);
  1025.                 RealToString(ScaleFactor, 1, 4, str2);
  1026.                 ShowMessage(concat(str1, cr, 'scale factor= ', str2));
  1027.                 j := 0;
  1028.                 for i := CurrentMin to CurrentMax do begin
  1029.                         PixelLUT^[j] := round((i - CurrentMin) * ScaleFactor + 1);
  1030.                         j := j + 1;
  1031.                     end;
  1032.                 for vloc := 0 to nlines - 1 do begin
  1033.                         if (vloc mod LinesPerUpdate) = 0 then
  1034.                             ShowAnimatedWatch;
  1035.                         GetIntLine(aLine);
  1036.                         for hloc := 0 to PixelsPerLine - 1 do begin
  1037.                                 value := aLine[hloc];
  1038.                                 if (DataType = SixteenBitsUnsigned) and (value < 0) then
  1039.                                     value := value + 65536;
  1040.                                 if value < CurrentMin then
  1041.                                     value := CurrentMin;
  1042.                                 if value > CurrentMax then
  1043.                                     value := CurrentMax;
  1044.                                 line[hloc] := PixelLUT^[value - CurrentMin];
  1045.                                 i := i + 1;
  1046.                             end;
  1047.                         PutLine(0, vloc, PixelsPerLine, line);
  1048.                     end;
  1049.                 if DensityCalibrated then begin
  1050.                         fit := StraightLine;
  1051.                         nCoefficients := 2;
  1052.                         coefficient[2] := (CurrentMin - CurrentMax) / 253.0;
  1053.                         coefficient[1] := CurrentMax - coefficient[2];
  1054.                         ZeroClip := false;
  1055.                         UpdateTitleBar;
  1056.                     end
  1057.                 else
  1058.                     DensityCalibrated := false;
  1059.                 DisposPtr(ptr(PixelLUT));
  1060.                 if DataH <> nil then begin
  1061.                         DisposHandle(DataH);
  1062.                         DataH := nil
  1063.                     end;
  1064.             end; {with}
  1065.     end;
  1066.  
  1067.  
  1068.     procedure RescaleToEightBits;
  1069.         var
  1070.             range: LongInt;
  1071.             err: OSErr;
  1072.             f: integer;
  1073.     begin
  1074.         with info^ do begin
  1075.                 ShowWatch;
  1076.                 KillRoi;
  1077.                 DisableDensitySlice;
  1078.                 err := fsopen(title, vref, f);
  1079.                 if CheckIO(err) <> 0 then
  1080.                     exit(RescaleToEightBits);
  1081.                 range := CurrentMax - CurrentMin;
  1082.                 if ColorStart > 0 then
  1083.                     CurrentMax := CurrentMax - round((ColorStart / 255) * range)
  1084.                 else
  1085.                     CurrentMax := AbsoluteMax;
  1086.                 if ColorEnd < 255 then
  1087.                     CurrentMin := CurrentMin + round(((255 - ColorEnd) / 255) * range)
  1088.                 else
  1089.                     CurrentMin := AbsoluteMin;
  1090.                 ScaleToEightBits(f);
  1091.                 err := fsclose(f);
  1092.                 InvertPic;
  1093.                 UpdatePicWindow;
  1094.                 ResetMap;
  1095.                 if DensityCalibrated then
  1096.                     GenerateValues;
  1097.             end;
  1098.     end;
  1099.  
  1100.  
  1101.     procedure Import16BitSlices (f: integer);
  1102.         var
  1103.             i, err: integer;
  1104.             h: handle;
  1105.             DataSize, nImages, MaxImages, FileSize: LongInt;
  1106.     begin
  1107.         with info^ do begin
  1108.                 nImages := ImportCustomSlices;
  1109.                 err := GetEof(f, FileSize);
  1110.                 MaxImages := (FileSize - ImportCustomOffset) div (ImageSize * 2);
  1111.                 if nImages > MaxImages then
  1112.                     nImages := MaxImages;
  1113.                 if nImages < 2 then
  1114.                     exit(Import16BitSlices);
  1115.                 ShowMessage(CmdPeriodToStop);
  1116.                 StackInfo := StackInfoPtr(NewPtr(SizeOf(StackInfoRec)));
  1117.                 if StackInfo = nil then
  1118.                     exit(Import16BitSlices);
  1119.             end; {with}
  1120.         with info^, info^.StackInfo^ do begin
  1121.                 nSlices := nImages;
  1122.                 SliceSpacing := 0.0;
  1123.                 LoopTime := 0.0;
  1124.                 PicBaseH[1] := PicBaseHandle;
  1125.                 revertable := false;
  1126.                 for i := 2 to nSlices do begin
  1127.                         h := NewHandle(PixMapSize);
  1128.                         if h = nil then begin
  1129.                                 nSlices := i - 1;
  1130.                                 leave;
  1131.                             end;
  1132.                         PicBaseH[i] := h;
  1133.                         CurrentSlice := i;
  1134.                         SelectSlice(i);
  1135.                         UpdateTitleBar;
  1136.                         DataSize := ImageSize;
  1137.                         AbsoluteMin := 0;
  1138.                         AbsoluteMax := 0;
  1139.                         CurrentMin := 0;
  1140.                         CurrentMax := 0;
  1141.                         if not ImportAutoScale then begin
  1142.                                 if ((ImportMax - ImportMin) > 65536.0) or (ImportMin > ImportMax) then begin
  1143.                                         ImportMin := 0.0;
  1144.                                         ImportMax := 255;
  1145.                                     end;
  1146.                                 CurrentMin := round(ImportMin);
  1147.                                 CurrentMax := round(ImportMax);
  1148.                             end;
  1149.                         ScaleToEightBits(f);
  1150.                         InvertPic;
  1151.                         UpdatePicWindow;
  1152.                         if CommandPeriod then begin
  1153.                                 beep;
  1154.                                 nSlices := i;
  1155.                                 wait(60);
  1156.                                 leave;
  1157.                             end;
  1158.                     end; {for}
  1159.                 if (MaxBlock < MinFree) and (nSlices > 1) then begin
  1160.                         repeat
  1161.                             DisposHandle(PicBaseH[nSlices]);
  1162.                             nSlices := nSlices - 1;
  1163.                         until (MaxBlock > MinFree) or (nSlices = 1);
  1164.                         PutMessage(concat('Not enough memory to open all ', long2str(nImages), ' slices in the stack.'));
  1165.                     end;
  1166.                 CurrentSlice := 1;
  1167.                 SelectSlice(CurrentSlice);
  1168.                 UpdateTitleBar;
  1169.                 UpdateWindowsMenuItem(PixMapSize * nSlices, title, PicNum);
  1170.             end;
  1171.     end;
  1172.  
  1173.  
  1174.     function Import16BitFile (fname: str255; vnum: integer): boolean;
  1175.         var
  1176.             ticks, ByteCount, i, NextTiffIFD: LongInt;
  1177.             err: OSErr;
  1178.             f: integer;
  1179.             line, pixel: integer;
  1180.     begin
  1181.         Import16BitFile := false;
  1182.         if ImportCustomWidth > MaxLine then
  1183.             exit(Import16BitFile);
  1184.         if not NewPicWindow(fname, ImportCustomWidth, ImportCustomHeight) then
  1185.             exit(Import16BitFile);
  1186.         ShowWatch;
  1187.         err := fsopen(fname, vNum, f);
  1188.         with info^ do begin
  1189.                 PictureType := imported;
  1190.                 ImageDataOffset := ImportCustomOffset;
  1191.                 DataType := ImportCustomDepth;
  1192.                 vref := vnum;
  1193.                 AbsoluteMin := 0;
  1194.                 AbsoluteMax := 0;
  1195.                 CurrentMin := 0;
  1196.                 CurrentMax := 0;
  1197.                 LittleEndian := ImportSwapBytes;
  1198.                 DensityCalibrated := ImportCalibrate;
  1199.                 if not ImportAutoScale then begin
  1200.                         if ((ImportMax - ImportMin) > 65536.0) or (ImportMin > ImportMax) then begin
  1201.                                 ImportMin := 0.0;
  1202.                                 ImportMax := 255;
  1203.                             end;
  1204.                         CurrentMin := round(ImportMin);
  1205.                         CurrentMax := round(ImportMax);
  1206.                     end;
  1207.                 DataH := GetBigHandle(PixMapSize * 2);
  1208.                 ScaleToEightBits(f);
  1209.                 if ImportCustomSlices > 1 then
  1210.                     Import16BitSlices(f);
  1211.                 err := fsclose(f);
  1212.                 InvertPic;
  1213.                 if PixMapSize > UndoBufSize then
  1214.                     PutWarning;
  1215.                 revertable := false;
  1216.             end; {with}
  1217.         Import16BitFile := true;
  1218.     end;
  1219.  
  1220.  
  1221.     procedure InitPictBuffer (howBig: LongInt);
  1222.     begin
  1223.         repeat
  1224.             PictBuffer := NewPtr(howBig);
  1225.             if PictBuffer = nil then
  1226.                 howBig := howBig div 2;
  1227.         until PictBuffer <> nil;
  1228.         DisposPtr(PictBuffer);
  1229.         PictBuffer := NewPtr(howBig div 2);
  1230.     end;
  1231.  
  1232.  
  1233.     procedure FillPictBuffer;
  1234.         var
  1235.             count: LongInt;
  1236.             err: OSErr;
  1237.     begin
  1238.         count := GetPtrSize(PictBuffer);
  1239.         if not fitsInPictBuffer then begin
  1240.                 err := FSRead(PictF, count, PictBuffer);
  1241.                 if err <> NoErr then
  1242.                     PictReadErr := true;
  1243.             end;
  1244.         bytesInPictBuffer := count;
  1245.         curPictBufPtr := PictBuffer;
  1246.     end;
  1247.  
  1248.  
  1249.     procedure GetPICTData (dataPtr: Ptr; byteCount: Integer);
  1250.     {Input picture spooler routine taken from Apple's PICTViewer example program.}
  1251.         var
  1252.             count: LongInt;
  1253.             anErr: OSErr;
  1254.     begin
  1255.         count := byteCount;
  1256.         repeat
  1257.             if bytesInPictBuffer >= count then begin
  1258.                     BlockMove(curPictBufPtr, dataPtr, count);
  1259.                     curPictBufPtr := Ptr(Ord4(curPictBufPtr) + count);
  1260.                     bytesInPictBuffer := bytesInPictBuffer - count;
  1261.                     count := 0;
  1262.                 end
  1263.             else begin        {Not enough in buffer}
  1264.                     if bytesInPictBuffer > 0 then begin
  1265.                             BlockMove(curPictBufPtr, dataPtr, bytesInPictBuffer);
  1266.                             dataPtr := Ptr(Ord4(dataPtr) + bytesInPictBuffer);
  1267.                             count := count - bytesInPictBuffer;
  1268.                         end;
  1269.                     FillPictBuffer;
  1270.                 end;
  1271.         until count = 0;
  1272.     end;
  1273.  
  1274.  
  1275.     procedure BitInfo (var srcBits: PixMap; var srcRect, dstRect: rect; mode: integer; maskRgn: rgnHandle);
  1276.         var
  1277.             i, size: integer;
  1278.     begin
  1279.         if BitInfoCount = 0 then begin
  1280.                 PictSrcRect := srcRect;
  1281.                 if srcBits.rowBytes < 0 then
  1282.                     with srcBits.pmTable^^ do begin{Make sure it is a PixMap.}
  1283.                             size := ctSize;
  1284.                             if size > 255 then
  1285.                                 size := 255;
  1286.                             if size > 0 then begin
  1287.                                     BitInfoCount := BitInfoCount + 1;
  1288.                                     if not UseExistingLUT then
  1289.                                         with info^ do begin
  1290.                                                 for i := 0 to size do
  1291.                                                     cTable[i].rgb := ctTable[i].rgb;
  1292.                                                 LutMode := ColorLut;
  1293.                                                 SetupPseudocolor;
  1294.                                             end;
  1295.                                 end;
  1296.                         end; {with}
  1297.             end;
  1298.     end;
  1299.  
  1300.  
  1301.     procedure GetLUTFromPict (thePict: PicHandle);
  1302.   {Refer to "Screen Dump FKEY for Color Picts", February 1988 MacTutor.}
  1303.         type
  1304.             myPicData = record
  1305.                     p: Picture;
  1306.                     ID: integer
  1307.                 end;
  1308.             myPicPtr = ^myPicData;
  1309.             myPicHdl = ^myPicPtr;
  1310.         var
  1311.             tempProcs: CQDProcs;
  1312.             SavePort: GrafPtr;
  1313.             err: osErr;
  1314.             TempPort: CGrafPort;
  1315.             limbo: rect;
  1316.             xscale, yscale: extended;
  1317.     begin
  1318.         GetPort(SavePort);
  1319.         OpenCPort(@TempPort);
  1320.         SetStdCProcs(tempProcs);
  1321.         tempProcs.bitsProc := @BitInfo;
  1322.         tempProcs.getPicProc := @GetPICTData;
  1323.         PictSrcRect := thePict^^.picFrame;
  1324.         BitInfoCount := 0;
  1325.         TempPort.grafProcs := @tempProcs;
  1326.         err := SetFPos(PictF, fsFromStart, 512 + SizeOf(Picture));
  1327.         FillPictBuffer;
  1328.         limbo := thePict^^.picFrame;
  1329.         OffsetRect(limbo, 10000, 10000);
  1330.         if not PictReadErr then
  1331.             DrawPicture(thePict, limbo);
  1332.         CloseCPort(@TempPort);
  1333.         SetPort(SavePort);
  1334.         with info^, PictSrcRect do begin
  1335.                 LoadLUT(cTable);
  1336.                 xScale := (right - left) / PixelsPerLine;
  1337.                 yScale := (bottom - top) / nLines;
  1338.                 if (xScale > 1.0) and ((PixelsPerLine * xScale) <= MaxLine) and ((xScale - yScale) < 0.1) then begin
  1339.                         PixelsPerLine := right - left;
  1340.                         nLines := bottom - top;
  1341.                     end;
  1342.             end; {with}
  1343.     end;
  1344.  
  1345.  
  1346.     function OpenPict;{(fname:str255; vnum:integer; Reverting:boolean):boolean}
  1347.         var
  1348.             err: OSErr;
  1349.             i: integer;
  1350.             iptr, p: ptr;
  1351.             PictSize, HowBig, NextTiffIFD: LongInt;
  1352.             thePict: PicHandle;
  1353.             tPort: GrafPtr;
  1354.             tempProcs: CQDProcs;
  1355.             SaveProcsPtr: QDProcsPtr;
  1356.             SaveInfo: InfoPtr;
  1357.             SaveGDevice: GDHandle;
  1358.  
  1359.         procedure Abort;
  1360.         begin
  1361.             if not reverting then begin
  1362.                     DisposPtr(pointer(Info));
  1363.                     Info := SaveInfo;
  1364.                     LoadLUT(info^.cTable);
  1365.                 end;
  1366.             if thePict <> nil then
  1367.                 DisposHandle(handle(thePict));
  1368.             if PictF <> 0 then
  1369.                 err := fsclose(PictF);
  1370.             exit(OpenPict);
  1371.         end;
  1372.  
  1373.     begin
  1374.         PictF := 0;
  1375.         thePict := nil;
  1376.         OpenPict := false;
  1377.         PictReadErr := false;
  1378.         ShowWatch;
  1379.         SaveInfo := Info;
  1380.         err := fsopen(fname, vNum, PictF);
  1381.         if CheckIO(err) <> 0 then
  1382.             Abort;
  1383.         if not Reverting then begin
  1384.                 iptr := NewPtr(SizeOf(PicInfo));
  1385.                 if iptr = nil then begin
  1386.                         PutMemoryAlert;
  1387.                         err := fsclose(PictF);
  1388.                         exit(OpenPict)
  1389.                     end;
  1390.                 Info := pointer(iptr);
  1391.                 CloneInfo(SaveInfo^, Info^);
  1392.             end;
  1393.         with Info^ do begin
  1394.                 err := GetEof(PictF, PictSize);
  1395.                 if CheckIO(err) <> 0 then
  1396.                     Abort;
  1397.                 PictSize := PictSize - 512;
  1398.                 if PictSize <= 0 then
  1399.                     Abort;
  1400.                 WhatToOpen := OpenPICT2;
  1401.                 if not OpenHeader(PictF, fname, vnum, NextTiffIFD) then
  1402.                     Abort;
  1403.                 thePict := PicHandle(NewHandle(SizeOf(Picture)));
  1404.                 if thePict = nil then
  1405.                     Abort;
  1406.                 err := SetFPos(PictF, fsFromStart, 512);
  1407.                 if CheckIO(err) <> 0 then
  1408.                     Abort;
  1409.                 howBig := SizeOf(Picture);
  1410.                 err := FSRead(PictF, howBig, Pointer(thePict^));
  1411.                 if CheckIO(err) <> 0 then
  1412.                     Abort;
  1413.                 with thePict^^.PicFrame do begin
  1414.                         nlines := bottom - top;
  1415.                         PixelsPerLine := right - left;
  1416.                     end;
  1417.          {....}
  1418.                 err := GetEof(PictF, howBig);
  1419.                 howBig := howBig - (512 + SizeOf(Picture));
  1420.                 InitPictBuffer(HowBig * 2);
  1421.                 if GetPtrSize(PictBuffer) >= howBig then begin
  1422.                         err := FSRead(PictF, howBig, PictBuffer);
  1423.                         if CheckIO(err) <> NoErr then begin
  1424.                                 DisposHandle(handle(thePict));
  1425.                                 DisposPtr(PictBuffer);
  1426.                                 err := fsclose(PictF);
  1427.                                 exit(OpenPict)
  1428.                             end;
  1429.                         fitsInPictBuffer := true;
  1430.                     end
  1431.                 else
  1432.                     fitsInPictBuffer := false;
  1433.                 if (LutMode = ColorLut) or (LutMode = CustomGrayscale) or (iVersion = 0) then
  1434.                     GetLUTFromPict(thePict);
  1435.                 if not Reverting then begin
  1436.                         p := GetImageMemory(SaveInfo);
  1437.                         if p = nil then begin
  1438.                                 DisposHandle(handle(thePict));
  1439.                                 DisposPtr(PictBuffer);
  1440.                                 err := fsclose(PictF);
  1441.                                 exit(OpenPict)
  1442.                             end;
  1443.                         PicBaseAddr := p;
  1444.                         MakeNewWindow(fname);
  1445.                     end;
  1446.                 if (PixMapSize > UndoBufSize) and (not Reverting) then begin
  1447.                         PutWarning;
  1448.                         ShowWatch;
  1449.                     end;
  1450.                 if isGrayScaleLUT then
  1451.                     ResetGrayMap;
  1452.                 SaveGDevice := GetGDevice;
  1453.                 SetGDevice(osGDevice);
  1454.                 GetPort(tPort);
  1455.                 SetPort(GrafPtr(osPort));
  1456.                 pmForeColor(BlackIndex);
  1457.                 pmBackColor(WhiteIndex);
  1458.                 RGBForeColor(BlackRGB);
  1459.                 RGBBackColor(WhiteRGB);
  1460.                 EraseRect(PicRect);
  1461.                 SaveProcsPtr := pointer(osPort^.grafProcs);
  1462.                 SetStdCProcs(tempProcs);
  1463.                 tempProcs.getPicProc := @GetPICTData;
  1464.                 osPort^.grafProcs := @TempProcs;
  1465.                 err := SetFPos(PictF, fsFromStart, 512 + SizeOf(Picture));
  1466.                 FillPictBuffer;
  1467.                 if not PictReadErr then
  1468.                     DrawPicture(thePict, PicRect);
  1469.                 osPort^.grafProcs := pointer(SaveProcsPtr);
  1470.                 DisposHandle(handle(thePict));
  1471.                 DisposPtr(PictBuffer);
  1472.                 pmForeColor(ForegroundIndex);
  1473.                 pmBackColor(BackgroundIndex);
  1474.                 SetPort(tPort);
  1475.                 SetGDevice(SaveGDevice);
  1476.                 vref := vnum;
  1477.                 PictureType := PictFile;
  1478.                 revertable := true;
  1479.             end; {with}
  1480.         err := fsclose(PictF);
  1481.         SetupUndo;
  1482.         if not PictReadErr then
  1483.             OpenPict := true;
  1484.     end;
  1485.  
  1486.  
  1487.     procedure GetCLUT (thePict: PicHandle);
  1488.         type
  1489.             myPicData = record
  1490.                     p: Picture;
  1491.                     ID: integer
  1492.                 end;
  1493.             myPicPtr = ^myPicData;
  1494.             myPicHdl = ^myPicPtr;
  1495.         var
  1496.             tempProcs: CQDProcs;
  1497.             SaveProcsPtr: QDProcsPtr;
  1498.             err: osErr;
  1499.     begin
  1500.         with info^ do begin
  1501.                 SetPort(GrafPtr(osPort));
  1502.                 SaveProcsPtr := pointer(wptr^.grafProcs);
  1503.                 SetStdCProcs(tempProcs);
  1504.                 tempProcs.bitsProc := @BitInfo;
  1505.                 BitInfoCount := 0;
  1506.                 osPort^.grafProcs := @tempProcs;
  1507.                 DrawPicture(thePict, thePict^^.picFrame);
  1508.                 osPort^.grafProcs := pointer(SaveProcsPtr);
  1509.                 LoadLUT(cTable);
  1510.             end;
  1511.     end;
  1512.  
  1513.  
  1514.     function OpenPICS (name: str255; fRefNum: integer): boolean;
  1515.         var
  1516.             RefNum, picID, hOffset, vOffset, nPICS, i: integer;
  1517.             err: OSErr;
  1518.             PicH: PicHandle;
  1519.             h: handle;
  1520.             MemError, Aborted: boolean;
  1521.             FrameRect: rect;
  1522.             SaveGDevice: GDHandle;
  1523.  
  1524.         procedure Abort;
  1525.         begin
  1526.             CloseResFile(RefNum);
  1527.             exit(OpenPICS);
  1528.         end;
  1529.  
  1530.     begin
  1531.         OpenPics := false;
  1532.         if MaxBlock < MinFree then begin
  1533.                 PutMessage('Insufficient memory to open PICS file.');
  1534.                 exit(OpenPICS);
  1535.             end;
  1536.         ShowWatch;
  1537.         err := SetVol(nil, fRefNum);
  1538.         RefNum := OpenResFile(name);
  1539.         if RefNum = -1 then begin
  1540.                 PutMessage('Unable to open PICS file.');
  1541.                 exit(OpenPICS);
  1542.             end;
  1543.         nPICS := Count1Resources('PICT');
  1544.         if nPICS < 1 then begin
  1545.                 PutMessage('No PICTs found.');
  1546.                 abort;
  1547.             end;
  1548.         PicH := GetPicture(128);
  1549.         if PicH = nil then
  1550.             Abort;
  1551.         FrameRect := PicH^^.PicFrame;
  1552.         with FrameRect do begin
  1553.                 hOffset := left;
  1554.                 vOffset := top;
  1555.                 right := right - hOffset;
  1556.                 bottom := bottom - vOffset;
  1557.                 left := 0;
  1558.                 top := 0;
  1559.             end;
  1560.         with FrameRect do
  1561.             if not NewPicWindow(name, right - left, bottom - top) then
  1562.                 Abort;
  1563.         with info^ do begin
  1564.                 revertable := false;
  1565.                 StackInfo := StackInfoPtr(NewPtr(SizeOf(StackInfoRec)));
  1566.                 if StackInfo = nil then
  1567.                     Abort;
  1568.                 with StackInfo^ do begin
  1569.                         SliceSpacing := 0.0;
  1570.                         LoopTime := 0.0;
  1571.                         nSlices := 1;
  1572.                         CurrentSlice := 1;
  1573.                         PicBaseH[1] := PicBaseHandle;
  1574.                     end;
  1575.             end;
  1576.         if not UseExistingLUT then
  1577.             GetCLUT(picH);
  1578.         with info^, Info^.StackInfo^ do begin
  1579.                 SaveGDevice := GetGDevice;
  1580.                 SetGDevice(osGDevice);
  1581.                 SetPort(GrafPtr(osPort));
  1582.                 pmBackColor(WhiteIndex);
  1583.                 EraseRect(PicRect);
  1584.                 DrawPicture(picH, PicRect);
  1585.                 DisposHandle(handle(picH));
  1586.                 SetGDevice(SaveGDevice);
  1587.                 UpdatePicWindow;
  1588.                 picID := 129;
  1589.                 MemError := false;
  1590.                 for i := 2 to nPICS do begin
  1591.                         PicH := GetPicture(picID);
  1592.                         if (PicH = nil) or (ResError <> NoErr) then
  1593.                             Leave;
  1594.                         h := GetBigHandle(PixMapSize);
  1595.                         if h = nil then begin
  1596.                                 if PicH <> nil then
  1597.                                     DisposHandle(handle(picH));
  1598.                                 MemError := true;
  1599.                                 Leave;
  1600.                             end;
  1601.                         nSlices := nSlices + 1;
  1602.                         CurrentSlice := CurrentSlice + 1;
  1603.                         PicBaseH[CurrentSlice] := h;
  1604.                         SelectSlice(CurrentSlice);
  1605.                         FrameRect := PicH^^.PicFrame;
  1606.                         with FrameRect do begin
  1607.                                 right := right - hOffset;
  1608.                                 bottom := bottom - vOffset;
  1609.                                 left := left - hOffset;
  1610.                                 top := top - vOffset;
  1611.                             end;
  1612.                         SetGDevice(osGDevice);
  1613.                         EraseRect(PicRect);
  1614.                         if not EqualRect(FrameRect, PicRect) then
  1615.                             BlockMove(PicBaseH[CurrentSlice - 1]^, PicBaseH[CurrentSlice]^, PixMapSize);
  1616.                         DrawPicture(picH, FrameRect);
  1617.                         DisposHandle(handle(picH));
  1618.                         SetGDevice(SaveGDevice);
  1619.                         UpdatePicWindow;
  1620.                         UpdateTitleBar;
  1621.                         Aborted := CommandPeriod;
  1622.                         if Aborted then begin
  1623.                                 beep;
  1624.                                 wait(60);
  1625.                                 Leave;
  1626.                             end;
  1627.                         picID := picID + 1;
  1628.                     end;
  1629.                 CloseResFile(RefNum);
  1630.                 if MemError then
  1631.                     PutMessage('Not enough memory to open all images in PICS file.');
  1632.                 CurrentSlice := 1;
  1633.                 SelectSlice(CurrentSlice);
  1634.                 PictureType := PicsFile;
  1635.                 Revertable := false;
  1636.                 UpdateTitleBar;
  1637.                 UpdateWindowsMenuItem(PixMapSize * nSlices, title, PicNum);
  1638.                 if not MemError and not Aborted then
  1639.                     OpenPICS := true;
  1640.             end; {with}
  1641.     end;
  1642.  
  1643.  
  1644. {$D-}
  1645.  
  1646.     procedure OpenAll (RefNum: integer);
  1647.       {Opens all appropriate files in a folder.    Original version contributed by Ira Rampil.}
  1648.         var
  1649.             OpenedOK: boolean;
  1650.             index: integer;
  1651.             name: Str255;
  1652.             ftype: OSType;
  1653.             err: OSErr;
  1654.             PB: HParamBlockRec;
  1655.     begin
  1656.         index := 0;
  1657.         while true do begin
  1658.                 index := index + 1;
  1659.                 with PB do begin
  1660.                         ioCompletion := nil;
  1661.                         ioNamePtr := @name;
  1662.                         ioVRefNUm := RefNum;
  1663.                         ioVersNum := 0;
  1664.                         ioFDirIndex := index;
  1665.                         err := PBGetFInfo(@PB, false);
  1666.                         if err = fnfErr then
  1667.                             exit(OpenAll);
  1668.                         ftype := ioFlFndrInfo.fdType;
  1669.                     end;
  1670.                 if ftype = 'IPIC' then begin
  1671.                         WhatToOpen := OpenImage;
  1672.                         if not OpenFile(name, RefNum) then
  1673.                             exit(OpenAll);
  1674.                     end
  1675.                 else if ftype = 'PICT' then begin
  1676.                         if not OpenPICT(name, RefNum, false) then
  1677.                             exit(OpenAll)
  1678.                     end
  1679.                 else if ftype = 'TIFF' then begin
  1680.                         WhatToOpen := OpenTiff;
  1681.                         if not OpenFile(name, RefNum) then
  1682.                             exit(OpenAll);
  1683.                     end
  1684.                 else if ftype = 'PNTG' then
  1685.                     if not OpenMacPaint(name, RefNum) then
  1686.                         exit(OpenAll);
  1687.             end; {while}
  1688.     end;
  1689.  
  1690.  
  1691.     function OpenDialogHook (item: integer; theDialog: DialogPtr): integer;
  1692.         const
  1693.             OpenAllID = 11;
  1694.             KeepLutID = 12;
  1695.         var
  1696.             i: integer;
  1697.     begin
  1698.         if (item = -1) and UseExistingLUT then
  1699.             SetDialogItem(theDialog, KeepLutID, 1);
  1700.         if item = OpenAllID then begin
  1701.                 OpenAllFiles := not OpenAllFiles;
  1702.                 SetDialogItem(theDialog, OpenAllID, ord(OpenAllFiles));
  1703.             end;
  1704.         if item = KeepLutID then begin
  1705.                 UseExistingLUT := not UseExistingLUT;
  1706.                 SetDialogItem(theDialog, KeepLutID, ord(UseExistingLut));
  1707.             end;
  1708.         OpenDialogHook := item;
  1709.     end;
  1710.  
  1711.  
  1712.     function isTiffFile (fname: str255; RefNum: integer): boolean;
  1713.   {Returns true if the first 16-bit word of the file contains 'MM' or 'II' and the second contains 42.}
  1714.         var
  1715.             f: integer;
  1716.             ByteCount: LongInt;
  1717.             hdr: array[1..512] of integer;
  1718.             err: OSErr;
  1719.     begin
  1720.         err := fsopen(fname, RefNum, f);
  1721.         err := SetFPos(f, fsFromStart, 0);
  1722.         ByteCount := 4;
  1723.         err := fsread(f, ByteCount, @hdr);
  1724.         isTiffFile := ((hdr[1] = $4949) and (hdr[2] = $2A00) or (hdr[1] = $4D4D) and (hdr[2] = $002A));
  1725.         err := fsclose(f);
  1726.     end;
  1727.  
  1728.  
  1729.     function DoOpen (FileName: str255; RefNum: integer): boolean;
  1730.         const
  1731.             MyDialogID = 70;
  1732.         var
  1733.             where: Point;
  1734.             reply: SFReply;
  1735.             b: boolean;
  1736.             sfPtr: ^SFTypeList;
  1737.             TypeList: array[0..10] of OSType;
  1738.             FileType: OSType;
  1739.             OKToContinue: boolean;
  1740.             FinderInfo: FInfo;
  1741.             err: OSErr;
  1742.     begin
  1743.         KillOperation;
  1744.         DisableDensitySlice;
  1745.         OpenAllFiles := false;
  1746.         UseExistingLUT := false;
  1747.         OKToContinue := false;
  1748.         if FileName = '' then begin
  1749.                 where.v := 50;
  1750.                 where.h := 50;
  1751.                 typeList[0] := 'IPIC';
  1752.                 typeList[1] := 'PICT';
  1753.                 typeList[2] := 'TIFF';
  1754.                 typeList[3] := 'ICOL';   {Color Tables}
  1755.                 typeList[4] := 'PX05'; {PixelPaint LUT}
  1756.                 typeList[5] := 'CLUT';  {Klutz LUT}
  1757.                 typeList[6] := 'drwC';  {Canvas LUT}
  1758.                 typeList[7] := 'PNTG';  {MacPaint}
  1759.                 typeList[8] := 'PICS';
  1760.                 typeList[9] := 'Iout';    {Outlines}
  1761.                 typeList[10] := 'TEXT';
  1762.                 sfPtr := @TypeList;
  1763.                 SFPGetFile(Where, '', nil, 11, sfPtr^, @OpenDialogHook, reply, MyDialogID, nil);
  1764.                 if reply.good then
  1765.                     with reply do begin
  1766.                             FileName := fname;
  1767.                             FileType := ftype;
  1768.                             RefNum := vRefNum;
  1769.                             DefaultRefNum := RefNum;
  1770.                             DefaultFileName := fname;
  1771.                             OKToContinue := true;
  1772.                         end;
  1773.                 if reply.good and OpenAllFiles then begin
  1774.                         OpenAll(RefNum);
  1775.                         exit(DoOpen);
  1776.                     end;
  1777.             end
  1778.         else begin
  1779.                 err := GetFInfo(FileName, RefNum, FinderInfo);
  1780.                 FileType := FinderInfo.fdType;
  1781.                 OKToContinue := true;
  1782.             end;
  1783.         DoOpen := OKToContinue;
  1784.         if OKToContinue then begin
  1785.                 if FileType = 'IPIC' then begin
  1786.                         WhatToOpen := OpenImage;
  1787.                         b := OpenFile(FileName, RefNum)
  1788.                     end
  1789.                 else if FileType = 'PICT' then begin
  1790.                         b := OpenPICT(FileName, RefNum, false)
  1791.                     end
  1792.                 else if FileType = 'TIFF' then begin
  1793.                         WhatToOpen := OpenTIFF;
  1794.                         b := OpenFile(FileName, RefNum)
  1795.                     end
  1796.                 else if FileType = 'ICOL' then
  1797.                     OpenColorTable(FileName, RefNum)
  1798.                 else if FileType = 'PX05' then
  1799.                     ImportPalette('PX05', FileName, RefNum)
  1800.                 else if FileType = 'CLUT' then
  1801.                     ImportPalette('CLUT', FileName, RefNum)
  1802.                 else if FileType = 'drwC' then
  1803.                     ImportPalette('PX05', FileName, RefNum)
  1804.                 else if FileType = 'PNTG' then
  1805.                     b := OpenMacPaint(FileName, RefNum)
  1806.                 else if FileType = 'PICS' then
  1807.                     b := OpenPICS(FileName, RefNum)
  1808.                 else if FileType = 'Iout' then
  1809.                     OpenOutline(FileName, RefNum)
  1810.                 else if FileType = 'TEXT' then begin
  1811.                         if isTiffFile(FileName, RefNum) and not OptionKeyWasDown then begin
  1812.                                 WhatToOpen := OpenTIFF;
  1813.                                 b := OpenFile(FileName, RefNum)
  1814.                             end
  1815.                         else
  1816.                             b := OpenTextFile(FileName, RefNum)
  1817.                     end
  1818.                 else begin
  1819.                         WhatToOpen := OpenUnknown;
  1820.                         b := OpenFile(FileName, RefNum)
  1821.                     end;
  1822.                 info^.ScaleToFitWindow := false;
  1823.                 if macro then
  1824.                     GenerateValues;
  1825.             end;
  1826.     end;
  1827.  
  1828.  
  1829.     procedure ImportAllFiles (RefNum: integer);
  1830.         var
  1831.             OpenedOK: boolean;
  1832.             index: integer;
  1833.             name: Str255;
  1834.             ftype: OSType;
  1835.             err: OSErr;
  1836.             PB: HParamBlockRec;
  1837.     begin
  1838.         index := 0;
  1839.         while true do begin
  1840.                 index := index + 1;
  1841.                 with PB do begin
  1842.                         ioCompletion := nil;
  1843.                         ioNamePtr := @name;
  1844.                         ioVRefNum := RefNum;
  1845.                         ioVersNum := 0;
  1846.                         ioFDirIndex := index;
  1847.                         err := PBGetFInfo(@PB, false);
  1848.                         if err = fnfErr then
  1849.                             exit(ImportAllFiles);
  1850.                         ftype := ioFlFndrInfo.fdType;
  1851.                     end;
  1852.                 if (WhatToOpen = OpenCustom) and (ImportCustomDepth <> EightBits) then begin
  1853.                         if not Import16BitFile(name, RefNum) then
  1854.                             exit(ImportAllFiles);
  1855.                     end
  1856.                 else begin
  1857.                         if not OpenFile(name, RefNum) then
  1858.                             exit(ImportAllFiles);
  1859.                     end;
  1860.                 if CommandPeriod then begin
  1861.                         beep;
  1862.                         exit(ImportAllFiles);
  1863.                     end;
  1864.             end; {while}
  1865.     end;
  1866.  
  1867.  
  1868.     procedure EditImportParameters;
  1869.         const
  1870.             WidthID = 2;
  1871.             HeightID = 3;
  1872.             OffsetID = 4;
  1873.             SlicesID = 5;
  1874.             FixedID = 6;
  1875.             MinID = 7;
  1876.             MaxID = 8;
  1877.         var
  1878.             mylog: DialogPtr;
  1879.             item, fwidth: integer;
  1880.     begin
  1881.         mylog := GetNewDialog(110, nil, pointer(-1));
  1882.         SetDNum(MyLog, WidthID, ImportCustomWidth);
  1883.         SelIText(MyLog, WidthID, 0, 32767);
  1884.         SetDNum(MyLog, HeightID, ImportCustomHeight);
  1885.         SetDNum(MyLog, SlicesID, ImportCustomSlices);
  1886.         SetDNum(MyLog, OffsetID, ImportCustomOffset);
  1887.         SetDialogItem(MyLog, FixedID, ord(not ImportAutoScale));
  1888.         if WhatToImport = ImportText then
  1889.             fwidth := 2
  1890.         else
  1891.             fwidth := 0;
  1892.         SetDReal(MyLog, MinID, ImportMin, fwidth);
  1893.         SetDReal(MyLog, MaxID, ImportMax, fwidth);
  1894.         OutlineButton(MyLog, ok, 16);
  1895.         repeat
  1896.             ModalDialog(nil, item);
  1897.             if item = WidthID then begin
  1898.                     ImportCustomWidth := GetDNum(MyLog, WidthID);
  1899.                     if (ImportCustomWidth < 0) or (ImportCustomWidth > MaxPicSize) then begin
  1900.                             ImportCustomWidth := 512;
  1901.                             SetDNum(MyLog, WidthID, ImportCustomWidth);
  1902.                         end;
  1903.                 end;
  1904.             if item = HeightID then begin
  1905.                     ImportCustomHeight := GetDNum(MyLog, HeightID);
  1906.                     if ImportCustomHeight < 0 then begin
  1907.                             ImportCustomHeight := 512;
  1908.                             SetDNum(MyLog, HeightID, ImportCustomHeight);
  1909.                         end;
  1910.                 end;
  1911.             if item = SlicesID then begin
  1912.                     ImportCustomSlices := GetDNum(MyLog, SlicesID);
  1913.                     if ImportCustomSlices < 0 then begin
  1914.                             ImportCustomSlices := 1;
  1915.                             SetDNum(MyLog, SlicesID, ImportCustomSlices);
  1916.                         end;
  1917.                 end;
  1918.             if item = OffsetIDstedExportName := concat(name, '(Coordinates)');
  1919.         end;
  1920.     end;
  1921.  
  1922.  
  1923.     function ExportHook (item: integer; theDialog: DialogPtr): integer;
  1924.         const
  1925.             EditTextID = 7;
  1926.             RawID = 9;
  1927.             xyCoordinatesID = 16;
  1928.         var
  1929.             i: integer;
  1930.             fname: str255;
  1931.             NameEdited: boolean;
  1932.     begin
  1933.         if item = -1 then {Initialize}
  1934.             SetDialogItem(theDialog, RawID + ord(ExportAsWhat), 1);
  1935.         fname := GetDString(theDialog, EditTextID);
  1936.         NameEdited := fname <> SuggestedExportName;
  1937.         if (item >= RawID) and (item <= xyCoordinatesID) then begin
  1938.                 ExportAsWhat := ExportAsWhatType(item - RawID);
  1939.                 if not NameEdited then begin
  1940.                         SetDString(theDialog, EditTextID, SuggestedExportName);
  1941.                         SelIText(theDialog, EditTextID, 0, 32767);
  1942.                     end;
  1943.                 for i := RawID to xyCoordinatesID do
  1944.                     SetDialogItem(theDialog, i, 0);
  1945.                 SetDialogItem(theDialog, item, 1);
  1946.             end;
  1947.         ExportHook := item;
  1948.     end;
  1949.  
  1950.  
  1951.     procedure Export (name: str255; RefNum: integer);
  1952.         const
  1953.             CustomDialogID = 100;
  1954.         var
  1955.             where: Point;
  1956.             reply: SFReply;
  1957.             isSelection: boolean;
  1958.             kind: integer;
  1959.             SaveAsState: SaveAsWhatType;
  1960.     begin
  1961.         with info^ do begin
  1962.                 if (name = '') or ((RefNum = 0) and (pos(':', name) = 0)) then begin
  1963.                         where.v := 50;
  1964.                         where.h := 50;
  1965.                         if name = '' then
  1966.                             name := SuggestedExportName;
  1967.                         SFPPutFile(Where, 'Save as?', name, @ExportHook, reply, CustomDialogID, nil);
  1968.                         if not reply.good then begin
  1969.                                 macro := false;
  1970.                                 exit(Export);
  1971.                             end;
  1972.                         with reply do begin
  1973.                                 name := fname;
  1974.                                 RefNum := vRefNum;
  1975.                                 DefaultRefNum := RefNum;
  1976.                             end;
  1977.                     end;
  1978.                 isSelection := RoiShowing and (RoiType = RectRoi);
  1979.                 case ExportAsWhat of
  1980.                     asRaw, asMCID:  begin
  1981.                             if ExportAsWhat = asMCID then
  1982.                                 InvertPic;
  1983.                             SaveAsState := SaveAsWhat;
  1984.                             if ExportAsWhat = AsRaw then
  1985.                                 SaveAsWhat := asRawData
  1986.                             else
  1987.                                 SaveAsWhat := SaveAsMCID;
  1988.                             if isSelection then
  1989.                                 SaveSelection(name, RefNum, false)
  1990.                             else
  1991.                                 SaveAsTIFF(name, RefNum, 0, 0, false);
  1992.                             SaveAsWhat := SaveAsState;
  1993.                         end;
  1994.                     AsText: 
  1995.                         ExportAsText(name, RefNum);
  1996.                     AsLUT: 
  1997.                         SaveLUT(name, RefNum);
  1998.                     asMeasurements: 
  1999.                         if mCount > 0 then
  2000.                             ExportMeasurements(name, RefNum)
  2001.                         else
  2002.                             PutMessage('Sorry, but no measurements are available to export.');
  2003.                     AsPlotValues: 
  2004.                         if PlotWindow <> nil then begin
  2005.                                 kind := WindowPeek(PlotWindow)^.WindowKind;
  2006.                                 case kind of
  2007.                                     ProfilePlotKind: 
  2008.                                         ConvertPlotToText;
  2009.                                     CalibrationPlotKind: 
  2010.                                         ConvertCalibrationCurveToText;
  2011.                                     otherwise
  2012.                                         TextBufSize := 0;
  2013.                                 end;
  2014.                                 SaveAsText(name, RefNum);
  2015.                             end
  2016.                         else
  2017.                             beep;
  2018.                     asHistogramValues: 
  2019.                         if HistoWindow <> nil then begin
  2020.                                 ConvertHistoToText;
  2021.                                 SaveAsText(name, RefNum);
  2022.                             end
  2023.                         else
  2024.                             beep;
  2025.                     asCoordinates: 
  2026.                         ExportCoordinates(name, RefNum);
  2027.                     otherwise
  2028.                         beep;
  2029.                 end; {case}
  2030.                 if (SaveAsWhat = asRawData) and (SaveAllState <> SaveAllStage2) then
  2031.                     SaveAsWhat := asTIFF;
  2032.             end; {with}
  2033.     end;
  2034.  
  2035.  
  2036.  
  2037. end.